﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Net;
using System.Net.Http;
using System.Net.Security;
using System.Security.Cryptography.X509Certificates;
using System.Text;
using System.Text.RegularExpressions;  

namespace WxPayAPI
{
    public class HttpClientHelper : IDisposable
    {
        private HttpClient httpClient;
        private HttpClientHandler handler;


        public HttpClientHelper()
        {
            InitHttpClient();
        }


        public HttpClientHelper(HttpClientHandler handler)
        {
            this.handler = handler;
            InitHttpClient();
        }


        /// <summary>  
        /// Url检查结果类  
        /// </summary>  
        public class UrlReachableResult
        {
            public bool Success;
            public string ErrorMsg;
            public string RawUrl;
            public string SourceUrl;
            public string StatusCode;


            public UrlReachableResult()
            {
                Success = false;
                ErrorMsg = string.Empty;
                RawUrl = string.Empty;
                SourceUrl = string.Empty;
                StatusCode = string.Empty;
            }
        }

        public UrlReachableResult checkUrlCanReached(string checkUrl, int cycleIndex = 0)
        {
            var result = new UrlReachableResult();
            result.SourceUrl = checkUrl;
            HttpResponseMessage response = null;
            try
            {
                ServicePointManager.ServerCertificateValidationCallback = new RemoteCertificateValidationCallback(CheckValidationResult);
                using (var task = httpClient.GetAsync(checkUrl, HttpCompletionOption.ResponseContentRead))
                {
                    task.Result.EnsureSuccessStatusCode();
                    response = task.Result;
                    result.StatusCode += response.StatusCode;
                    result.RawUrl = response.RequestMessage.RequestUri.ToString();
                    result.Success = true;


                    var contentHtml = response.Content.ReadAsStringAsync().Result;
                    var match = Regex.Match(contentHtml, "<meta[^>]+http-equiv=[\"']{0,1}refresh[\"']{0,1}[^>]*>");
                    if (match.Success && !contentHtml.Contains("<script"))
                    {
                        var metaMatches = Regex.Match(match.Value, "content=\\s*[\"'][^\"']*url=([^\"';]*)");
                        if (metaMatches.Success && metaMatches.Groups.Count >= 2 && !string.IsNullOrWhiteSpace(metaMatches.Groups[1].Value))
                        {
                            var innerResult = checkUrlCanReached(metaMatches.Groups[1].Value, ++cycleIndex);
                            innerResult.SourceUrl = checkUrl;
                            result = innerResult;
                        }
                    }
                }
            }
            catch (HttpRequestException ex)
            {
                result.ErrorMsg = "无法打开链接地址！";
            }
            catch (Exception ex)
            {
                result.ErrorMsg = ex.ToString();
            }
            finally
            {
                if (response != null)
                    response.Dispose();
            }
            return result;
        }


        private static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
        {
            return true; //总是接受    
        }


        private void InitHttpClient()
        {
            if (handler == null)
            {
                handler = new HttpClientHandler();
                handler.AllowAutoRedirect = true;//支持重定向
            }
            httpClient = new HttpClient(handler);
            //设置客户端可以接收的类型(接收所有) 如果不添加，请求有些服务器会报错  
            httpClient.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("*/*"));
            // Limit the max buffer size for the response so we don't get overwhelmed  
            //httpClient.MaxResponseContentBufferSize = 256000;  
            // Add a user-agent header  

            //httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
            //必须模拟微信浏览器
            //httpClient.DefaultRequestHeaders.Add("user-agent", "Mozilla/5.0 (iPhone; CPU iPhone OS 5_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Mobile/9B176 MicroMessenger/4.3.2");
            httpClient.DefaultRequestHeaders.Add("user-agent", " Mozilla/5.0 (Linux; U; Android 2.3.6; zh-cn; GT-S5660 Build/GINGERBREAD) AppleWebKit/533.1 (KHTML, like Gecko) Version/4.0 Mobile Safari/533.1 MicroMessenger/4.5.255");
        }


        public void Dispose()
        {
            if (httpClient != null)
                httpClient.Dispose();
        }
    } 
}